﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Shapes = System.Windows.Shapes;
using FeatureModelCore;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using System.Windows.Shapes;
using FeatureModelCore.FMShapes;
using System.Windows.Input;
using FeatureModelCore.FMInterface;
using FeatureModelCore.Layout;

namespace FeatureModelTool.FeatureModelGraphical.GraphicalControls
{
    public class Control_TreeNode : IControl
    {
        public static readonly double DEFAULT_FONT_SIZE = 12;
        public static readonly Brush COMMON_STROKE_COLOR = Brushes.Black;
        public readonly static Brush DEAD_STROKE_COLOR = Brushes.DarkRed;


        public readonly static Brush COMMON_BG_COLOR = Brushes.LightGreen;
        public readonly static Brush FOCUS_BG_COLOR = Brushes.DarkBlue;

        public readonly static Brush COMMON_FORE_COLOR = Brushes.Black;
        public readonly static Brush FOCUS_FORE_COLOR = Brushes.White;

        #region Properties
        public IFeature FeatureInstance { get { return _node; } }
        public FeatureModelGraphicalView Canvas { get { return _canvas; } }

        public Brush Background { get { if (IsFocus) return FOCUS_BG_COLOR; return COMMON_BG_COLOR; } }
        public Brush StrokeColor { get { return COMMON_STROKE_COLOR; } }
        public Brush ForeColor
        {
            get
            {
                if (_isFocus)
                    return FOCUS_FORE_COLOR;
                return COMMON_FORE_COLOR;
            }
        }
        public int BorderThickness
        {
            get
            {
                if (_isFocus)
                    return FeatureModelGraphicalView.FOCUS_THICKNESS;
                return FeatureModelGraphicalView.DEFAULT_THICKNESS;
            }
        }
        public bool IsFocus { get { return _isFocus; } }
        #endregion

        #region Fields
        private IFeature _node;
        private FeatureModelGraphicalView _canvas;
        private bool _isFocus;

        private bool _isPressed;
        private FMPoint _orgPlace;

        private Label _textbox;
        #endregion

        public Control_TreeNode(FeatureModelGraphicalView canvas, IFeature node)
            : base()
        {
            _node = node;
            _canvas = canvas;
            _isFocus = false;

            _isPressed = false;
            _orgPlace = null;

            _textbox = new Label();

            setLayout();

            #region Set Mouse Event Handler
            _textbox.MouseMove += new MouseEventHandler(MouseMove);
            _textbox.MouseLeftButtonDown += new MouseButtonEventHandler(MouseLeftClickDown);
            _textbox.MouseLeftButtonUp += new MouseButtonEventHandler(MouseLeftClickUp);
            #endregion

            #region Set Position
            double width = _node.Shape.Width;
            double height = _node.Shape.Height;
            _textbox.Width = width;
            _textbox.Height = height;
            RefreshPosition();
            #endregion

            _textbox.Content = FeatureInstance.FeatureName;
        }

        public UIElement[] ToUIElement()
        {
            return new UIElement[] { _textbox };
        }

        #region Focus
        /// <summary>
        /// Set Focus
        /// </summary>
        public void Focus()
        {
            this._canvas.ClearFocus();
            this._isFocus = true;
            setLayout();

            // set property box_isFocus
            MainWindow mainWin = MainWindow.GetCurrentWindowsInstance(this._textbox);
            if (mainWin == null)
            {
                return;
            }
            mainWin.SetPropertyInfo(this.FeatureInstance);
        }
        /// <summary>
        /// Clear Focus
        /// </summary>
        public void ClearFocus()
        {
            _isFocus = false;
            setLayout();
        }
        #endregion

        #region Set Position
        public void SetPosition(FMPoint point, bool toRefresh)
        {
            SetPosition(point.X, point.Y, toRefresh);
        }

        public void SetPosition(double x, double y, bool toRefresh)
        {
            double top = TreeLayout.MARGIN + TreeLayout.DEFAULT_HEIGHT / 2;
            double left = TreeLayout.MARGIN + TreeLayout.DEFAULT_WIDTH / 2;
            if (y < top)
            {
                y = top;
            }
            if (x < left)
            {
                x = left;
            }

            // set group relationship
            double orgX = _node.Shape.Center.X;
            double orgY = _node.Shape.Center.Y;
            IRelation[] grList = _node.ChildrenGroupRelationshipes;
            if (grList != null || grList.Length != 0)
            {
                foreach (FeatureTreeGroupRelationship gr in grList)
                {
                    double grOrgX = gr.Shape.Center.X;
                    double grOrgY = gr.Shape.Center.Y;

                    double grCurX = x - orgX + grOrgX;
                    double grCurY = y - orgY + grOrgY;
                    double radius = gr.Shape.Radius;

                    gr.Shape = new FMCircle(radius, new FMPoint(grCurX, grCurY));
                }
            }


            FMPoint point = new FMPoint(x, y);
            double width = _node.Shape.Width;
            double height = _node.Shape.Height;
            FMRectangle rect = new FMRectangle(width, height, point);

            this._node.Shape = rect;
            if (toRefresh) _canvas.RefreshPosition(this, null);
        }
        #endregion

        #region Mouse Event Hanlder
        /// <summary>
        /// Mouse Move
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void MouseMove(object sender, MouseEventArgs args)
        {
            if (args.LeftButton != MouseButtonState.Pressed)
            {
                return;
            }
            if (_isPressed == false
                || _orgPlace == null)
            {
                return;
            }

            Point curPt = args.MouseDevice.GetPosition(this._canvas);
            double curMouseX, curMouseY;
            curMouseX = curPt.X;
            curMouseY = curPt.Y;

            double orgMouseX, orgMouseY;
            lock (_orgPlace)
            {
                orgMouseX = _orgPlace.X;
                orgMouseY = _orgPlace.Y;

                // reset org place
                _orgPlace = new FMPoint(curMouseX, curMouseY);
            }

            double orgShapeX, orgShapeY;
            orgShapeX = _node.Shape.Center.X;
            orgShapeY = _node.Shape.Center.Y;

            double curShapeX = curMouseX - orgMouseX + orgShapeX;
            double curShapeY = curMouseY - orgMouseY + orgShapeY;

            curShapeX = curMouseX - orgMouseX + orgShapeX;
            curShapeY = curMouseY - orgMouseY + orgShapeY;
            this.SetPosition(curShapeX, curShapeY, true);
        }

        /// <summary>
        /// Mouse Left Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void MouseLeftClickDown(object sender, MouseButtonEventArgs args)
        {
            //// set cross tree constraint
            //if (_panel.IsInCreatingCrossTreeConstraint)
            //{
            //    if (_panel.CrossTreeConstraintCurCount == 0)
            //    {
            //        _panel.FmCrossTreeNode1 = this.BindObject;
            //        _panel.CrossTreeConstraintCurCount = 1;
            //    }
            //    else if (_panel.CrossTreeConstraintCurCount == 1)
            //    {
            //        if (_panel.FmCrossTreeNode1 != this.BindObject)
            //        {
            //            _panel.IsInCreatingCrossTreeConstraint = false;

            //            AddNewCrossTreeConstraintWindow addwin =
            //                new AddNewCrossTreeConstraintWindow(_panel
            //                , _panel.FmCrossTreeNode1.ID, this.BindObject.ID);
            //            addwin.ShowDialog();
            //        }
            //    }
            //    else
            //    {
            //        throw new Exception();
            //    }
            //}

            // set move information
            Point pt = args.MouseDevice.GetPosition(this._canvas);
            this._orgPlace = new FMPoint(pt.X, pt.Y);
            this._isPressed = true;

            // set focus
            this.Focus();

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void MouseLeftClickUp(object sender, MouseButtonEventArgs args)
        {
            _isPressed = false;
        }
        #endregion


        private void setLayout()
        {
            #region Layout
            _textbox.HorizontalContentAlignment = HorizontalAlignment.Center;
            _textbox.VerticalContentAlignment = VerticalAlignment.Center;
            _textbox.FontFamily = new FontFamily("Consolas");
            _textbox.FontSize = Control_TreeNode.DEFAULT_FONT_SIZE;
            _textbox.BorderBrush = StrokeColor;
            _textbox.Foreground = ForeColor;

            _textbox.BorderThickness = new Thickness(BorderThickness, BorderThickness
                , BorderThickness, BorderThickness);
            _textbox.Padding = new Thickness(0, 0, 0, 0);
            _textbox.Background = this.Background;
            #endregion
        }

        public void RefreshPosition()
        {
            double width = _node.Shape.Width;
            double height = _node.Shape.Height;
            double x = _node.Shape.Center.X;
            double y = _node.Shape.Center.Y;

            _textbox.Width = width;
            _textbox.Height = height;
            _textbox.Margin = new Thickness(x - width / 2, y - height / 2, 0, 0);

        }
    }
}
